package com.xjq.config;

import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.YieldingWaitStrategy;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import com.xjq.lession1.LongEvent;
import com.xjq.lession1.LongEventFactory;
import com.xjq.lession1.LongEventHandler;
import com.xjq.lession1.LongEventProducer;
import com.xjq.lession2.*;
import com.xjq.lesson3.UserInfoEventMutiProducer;
import com.xjq.lesson4.UserInfoEventSingleProducerMutiCustomerNoRepeat;
import com.xjq.lesson4.UserInfoWork2Handler;
import com.xjq.lesson4.UserInfoWorkHandler;
import com.xjq.lesson5.UserInfoEvent3Handler;
import com.xjq.lesson5.UserInfoEventSingleProducerMutiCustomerOrder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * create by xiao_qiang_01@163.com
 *
 * 2023/9/29
 */
@Configuration
public class DisruptorConfig {

    /**
     * 接收 Long 类型数据
     * @return
     */
    @Bean
    public LongEventProducer getLongEventProducer(){
        //1. 创建disruptor
        Disruptor<LongEvent> disruptor = new Disruptor(
                new LongEventFactory(),
                // RingBuffer 大小，必须是2的N次方
                1024 * 1024,
                Executors.defaultThreadFactory(),
                // 单个生产者，如果有多个生产者必须使用 ProducerType.MULTI
                ProducerType.SINGLE,
                // 生产者和消费者的平衡策略
                new YieldingWaitStrategy()
        );

        //2. 连接消费事件方法
        disruptor.handleEventsWith(new LongEventHandler());
        //3. 启动
        disruptor.start();

        //4. 发布事件
        RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer();

        return new LongEventProducer(ringBuffer);
    }

    /**
     * 单生产者多消费者场景
     * @return
     */
    @Bean
    public UserInfoEventProducer getUserInfoEventProducer(){
        Disruptor<UserInfoEvent> disruptor = new Disruptor(
                new UserInfoEventFactory(),
                1024 * 1024,
                Executors.defaultThreadFactory(),
                ProducerType.SINGLE,
                new YieldingWaitStrategy()
        );

        //2. 连接消费事件方法
        disruptor.handleEventsWith(new UserInfoEventHandler(), new UserInfoEvent2Handler());
        //3. 启动
        disruptor.start();

        //4. 发布事件
        RingBuffer<UserInfoEvent> ringBuffer = disruptor.getRingBuffer();

        return new UserInfoEventProducer(ringBuffer);
    }

    /**
     * 多生产者单消费者场景
     * @return
     */
    @Bean
    public UserInfoEventMutiProducer getUserInfoEventMutiProducer(){
        Disruptor<UserInfoEvent> disruptor = new Disruptor(
                new UserInfoEventFactory(),
                1024 * 1024,
                Executors.defaultThreadFactory(),
                ProducerType.MULTI,
                new YieldingWaitStrategy()
        );

        //2. 连接消费事件方法
        disruptor.handleEventsWith(new UserInfoEventHandler());
        //3. 启动
        disruptor.start();

        //4. 发布事件
        RingBuffer<UserInfoEvent> ringBuffer = disruptor.getRingBuffer();

        return new UserInfoEventMutiProducer(ringBuffer);
    }

    /**
     * 单生产者多消费者竞争场景
     * @return
     */
    @Bean
    public UserInfoEventSingleProducerMutiCustomerNoRepeat getUserInfoEventSingleProducerMutiCustomerNoRepeat(){
        Disruptor<UserInfoEvent> disruptor = new Disruptor(
                new UserInfoEventFactory(),
                1024 * 1024,
                Executors.defaultThreadFactory(),
                ProducerType.MULTI,
                new YieldingWaitStrategy()
        );

        //2. 下面两个消费者只有一个成功消费
        disruptor.handleEventsWithWorkerPool(new UserInfoWorkHandler(), new UserInfoWork2Handler());
        //3. 启动
        disruptor.start();

        //4. 发布事件
        RingBuffer<UserInfoEvent> ringBuffer = disruptor.getRingBuffer();

        return new UserInfoEventSingleProducerMutiCustomerNoRepeat(ringBuffer);
    }

    /**
     * 单生产者多消费者串行消费场景
     * @return
     */
    @Bean
    public UserInfoEventSingleProducerMutiCustomerOrder getUserInfoEventSingleProducerMutiCustomerOrder(){
        Disruptor<UserInfoEvent> disruptor = new Disruptor(
                new UserInfoEventFactory(),
                1024 * 1024,
                Executors.defaultThreadFactory(),
                ProducerType.MULTI,
                new YieldingWaitStrategy()
        );

        //2. 连接消费事件方法
        disruptor.handleEventsWith(new UserInfoEventHandler())
                .then(new UserInfoEvent2Handler())
                .then(new UserInfoEvent3Handler());
        //3. 启动
        disruptor.start();

        //4. 发布事件
        RingBuffer<UserInfoEvent> ringBuffer = disruptor.getRingBuffer();

        return new UserInfoEventSingleProducerMutiCustomerOrder(ringBuffer);
    }

}
